﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.ServiceModel.Channels;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using TaskFactoryBugSample.Annotations;
using TaskFactoryBugSample.BackendServiceReference;

namespace TaskFactoryBugSample
{
  public class MainWindowViewModel : INotifyPropertyChanged
  {
    private readonly ObservableCollection<BackendServiceReference.Data> _master = new ObservableCollection<BackendServiceReference.Data>();
    private readonly ObservableCollection<BackendServiceReference.Data> _detail = new ObservableCollection<BackendServiceReference.Data>();
    private BackendServiceReference.Data _currentMaster;
    private BackendServiceReference.Data _currentDetail;
    private BackendService _backendService;
    private ICommand _refresh;

    public MainWindowViewModel()
    {
      _refresh = new DelegateCommand(RefreshMaster);
    }

    private void RefreshMaster()
    {
      var client = new BackendClient();

      Task<IEnumerable<BackendServiceReference.Data>>.Factory.FromAsync(
        client.BeginGetMasters,
        client.EndGetMasters,
        null)
        .ContinueWith(t =>
        {
          _master.Clear();
          foreach (var master in t.Result)
          {
            _master.Add(master);
          }
          if (_master.Count > 0) CurrentMaster = _master.First();
          else CurrentMaster = null;
        }, TaskScheduler.FromCurrentSynchronizationContext());
      
    }

    private void RefreshDetail()
    {
      if (CurrentMaster == null) return;

      var client = new BackendClient();

      Task<IEnumerable<BackendServiceReference.Data>>.Factory.FromAsync(
        client.BeginGetDetails,
        client.EndGetDetails,
        CurrentMaster.Message,
        null)
        .ContinueWith(t =>
        {
          _detail.Clear();
          foreach (var detail in t.Result)
          {
            _detail.Add(detail);
          }
          if (_detail.Count > 0) CurrentDetail = _detail.First();
          else CurrentDetail = null;
        }, TaskScheduler.FromCurrentSynchronizationContext());
      
    }


    public void Loaded()
    {
      _backendService = new BackendService();
      _backendService.Start();
    }

    public void Unloaded()
    {
      _backendService.Stop();
    }

    public ICommand Refresh
    {
      get { return _refresh; }
    }

    public ObservableCollection<BackendServiceReference.Data> Master
    {
      get { return _master; }
    }

    public ObservableCollection<BackendServiceReference.Data> Detail
    {
      get { return _detail; }
    }

    public BackendServiceReference.Data CurrentMaster
    {
      get { return _currentMaster; }
      set
      {
        if (value == _currentMaster) return;
        _currentMaster = value;
        OnPropertyChanged("CurrentMaster");
        RefreshDetail();
      }
    }

    public BackendServiceReference.Data CurrentDetail
    {
      get { return _currentDetail; }
      set
      {
        if (value == _currentDetail) return;
        _currentDetail = value;
        OnPropertyChanged("CurrentDetail");
      }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged(string propertyName)
    {
      var handler = PropertyChanged;
      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
  }
}